package com.zhumo.sz.table.hive;

import com.google.common.base.CaseFormat;
import com.zhumo.sz.common.annotation.AlwaysAttribute;
import com.zhumo.sz.common.annotation.NestedEntity;
import com.zhumo.sz.entity.bike.SharedBikeOrderDetail;
import com.zhumo.sz.entity.subway.SubwayStationInfo;
import com.zhumo.sz.table.DBGenerator;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Properties;

/**
 * @author jiaqi.zhu
 * @time 2024.4.3
 * @comment 根据entity 或 mysql 自动映射建表
 */
@Slf4j
@Data
@NoArgsConstructor
public class HiveDDLGenerator implements DBGenerator {

    private String schema;

    /**
     * 目前只支持string类型 支持多个分区 逗号分割
     */
    private String partitionColumn;

    private boolean isExternal;

    private String stored;

    private String formation;

    private String location;

    private Class<?> entityClass;


    private String tableName;


    private Properties tableProperties;

    public HiveDDLGenerator(String schema,String partitionColumn,boolean isExternal,
                            String stored,String formation,String location,Properties tableProperties,Class<?> entityClass){
        this.formation = formation;
        this.isExternal = isExternal;
        this.schema = schema;
        this.partitionColumn = partitionColumn;
        this.stored = stored;
        this.location = location;
        this.tableProperties = tableProperties;
        this.entityClass = entityClass;
    }

   public HiveDDLGenerator(String schema,String partitionColumn,String stored,String formation,String tableName){
        this.schema = schema;
        this.partitionColumn = partitionColumn;
        this.stored = stored;
        this.formation =formation;
        this.tableName = tableName;
   }

    @Override
    public String open(String schema) {
        return null;

    }

    public String build(){
        log.info("正在生成sql ddl .........");
        StringBuilder tableCreateBuilder = new StringBuilder("create ");
        if (isExternal){
            tableCreateBuilder.append(HiveDDLConfig.EXTERNAL_TABLE);
        }
        tableCreateBuilder.append("table if not exists ");
        String name = Objects.nonNull(tableName) ? schema + "." + tableName :
                (Objects.isNull(entityClass) ? null : schema + "." +
                        CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entityClass.getSimpleName()));
        //驼峰转下划线
        if (Objects.isNull(name)){
            return "";
        }
        tableCreateBuilder.append(name).append("(").append("\n");
        Field[] declaredFields = entityClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            if (declaredField.getAnnotation(HiveIgnore.class) == null){
                //判断嵌套注解
                if (declaredField.getAnnotation(NestedEntity.class) != null) {
                    //嵌套属性值作为字段值
                    Class<?> nestedClass = declaredField.getType();
                    for (Field nestedField : nestedClass.getDeclaredFields()) {
                        nestedField.setAccessible(true);
                        AlwaysAttribute alwaysAttribute = declaredField.getAnnotation(AlwaysAttribute.class);
                        if (alwaysAttribute != null) {
                            String value = alwaysAttribute.value();
                            String nestedFieldName = nestedField.getName();
                            //将原属性首字母转为大写
                            String alwaysFieldName = value + nestedFieldName.substring(0, 1).toUpperCase() + nestedFieldName.substring(1);
                            tableCreateBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, alwaysFieldName));
                        } else {
                            tableCreateBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, nestedField.getName()));
                        }
                        //获取数据类型和注释
                        Class<?> nestType = nestedField.getType();
                        String nestColumnType = getColumnType(nestType);
                        tableCreateBuilder.append(" ").append(nestColumnType).append(" ");
                        ApiModelProperty commentAn = nestedField.getAnnotation(ApiModelProperty.class);
                        if (Objects.nonNull(commentAn) && !(commentAn.value().replaceAll("\\s", "").length() == 0)) {
                            tableCreateBuilder.append("comment ").append("'").append(commentAn.value()).append("'");
                        }
                        tableCreateBuilder.append(",");
                    }
                    tableCreateBuilder.delete(tableCreateBuilder.length()-1,tableCreateBuilder.length());
                }else {
                    String colName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, declaredField.getName());
                    tableCreateBuilder.append(colName);
                    Class<?> type = declaredField.getType();
                    String columnType = getColumnType(type);
                    //获取swagger注解 获取不到则没有注释生成
                    tableCreateBuilder.append(" ").append(columnType).append(" ");
                    ApiModelProperty commentAn = declaredField.getAnnotation(ApiModelProperty.class);
                    if (Objects.nonNull(commentAn) && !(commentAn.value().replaceAll("\\s", "")
                            .length() == 0)) {
                        tableCreateBuilder.append("comment ").append("'").append(commentAn.value()).append("'");
                    }
                }
                tableCreateBuilder.append(",");
            }
        }
        tableCreateBuilder.deleteCharAt(tableCreateBuilder.length() - 1);
//        tableCreateBuilder.delete(tableCreateBuilder.length()-1,tableCreateBuilder.length());
        tableCreateBuilder.append("\n").append(")").append("\n");
        if (Objects.nonNull(partitionColumn) && !(partitionColumn.replaceAll("\\s","").length()==0)){
            String[] partitionArr = partitionColumn.split(",");
            tableCreateBuilder.append(HiveDDLConfig.PARTITION_FORMAT).append("(");
            for (String partition : partitionArr) {
                tableCreateBuilder.append(partition).append(" ").append("string").append(",");
            }
            tableCreateBuilder.delete(tableCreateBuilder.length()-1,tableCreateBuilder.length());
            tableCreateBuilder.append(") ");
            tableCreateBuilder.append("\n");
        }
        if (Objects.nonNull(stored) && !(stored.replaceAll("\\s","").length()==0)){
            tableCreateBuilder.append(HiveDDLConfig.STORE_FORMAT).append(stored);
            tableCreateBuilder.append("\n");
        }
        if (Objects.nonNull(formation) && !(formation.replaceAll("\\s","").length()==0)){
            tableCreateBuilder.append(HiveDDLConfig.ROW_FORMAT).append("'").append(formation).append("' ");
            tableCreateBuilder.append("\n");
        }
        if (Objects.nonNull(location) && !(location.replaceAll("\\s","").length()==0)){
            tableCreateBuilder.append(HiveDDLConfig.LOCATION_FORMAT).append("'").append(location).append("'").append(" ");
            tableCreateBuilder.append("\n");
        }
        if (Objects.nonNull(tableProperties) && !(tableProperties.size() ==0 )){
            tableCreateBuilder.append(HiveDDLConfig.makeTableProperties(tableProperties));
        }
        tableCreateBuilder.append(";"); //end
        String sql = tableCreateBuilder.toString();
        System.out.println("********************************************************************************************");
        System.out.println(sql);
        System.out.println("********************************************************************************************");
        log.info("生成完成");
        return sql;
    }

    public static String getColumnType(Class<?> entityClass){
        if (Objects.isNull(entityClass)){
            throw new RuntimeException("类型异常");
        }
        if (entityClass.equals(String.class)){
            return "string";
        }
        if (entityClass.equals(Long.class)){
            return "bigint";
        }
        if (entityClass.equals(BigDecimal.class)){
            return "decimal(10,3)";
        }
        if (entityClass.equals(Timestamp.class)){
            return "timestamp";
        }
        if (entityClass.equals(Integer.class)){
            return "int";
        }
        if (entityClass.equals(Double.class)){
            return "double";
        }
        if (entityClass.equals(Float.class)){
            return "float";
        }
        return "string";
    }

    @Override
    public String drop() {
        return "";
    }

    public static void main(String[] args) {
        HiveDDLGenerator hiveDDLGenerator = new HiveDDLGenerator("sz_tra","line_code",true,"orc","\\t",
                "/hive/warehouse/sz_tra/ods/subway_station_info",null, SharedBikeOrderDetail.class);
        String sql = hiveDDLGenerator.build();

    }

}
